Studio degli elementi <html> e <body> con riferimento alle proprietà css relative al posizionamento e al background

In questa pagina cercheremo di chiarire che cosa sono e come funzionano gli elementi <html> e <body>. Forse l'argomento apparirà banale, ma a giudicare dal numero di domande che vengono poste in proposito nei vari forum presenti sul web, evidentemente non risulta del tutto chiaro (o almeno non lo è per tutti).

L'argomento ci fornirà inoltre occasione di toccare altri aspetti del comportamento dei vari elementi che costituiscono una pagina web e della loro formattazione attraverso i fogli di stile.

La pagina web che utilizzeremo per "sperimentare" è costituita unicamente da un elemento <h1> e un elemento <p>, dei quali, nel foglio di stile, ci limitiamo a definire font-family e font-size. Per quanto riguarda gli elementi <html> e <body>, inizieremo dal caso più semplice, in cui non assegneremo alcuna proprietà css, se non un semplice bordo che ci aiuterà ad individuare la composizione del layout della pagina:

html {
 border: solid 3px black;
}
body {
 border: solid 3px red;
}

Come si vede nella figura, gli elementi <body> e <html> occupano orizzontalmente l'intero spazio disponibile (poiché sono elementi block), mentre verticalmente assumono la dimensione (l'altezza) necessaria a contenere gli elementi <h1> e <p>.

Ora modifichiamo la larghezza dell'elemento <html>:

html {
 border: solid 3px black;
 width: 60%;
}
body {
 border: solid 3px red;
}

Quindi lo centriamo orizzontalmente:

html {
 border: solid 3px black;
 width: 60%;
 margin: auto;
}
body {
 border: solid 3px red;
}

Risultato analogo ai fini pratici si ottiene lasciando inalterata (al 100%) la larghezza di <html> e "stringendo" e centrando l'elemento <body>:

html {
 border: solid 3px black;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
}

Ora proviamo ad aggiungere un colore di sfondo: sebbene né <html><body> occupino l'intero viewport (l'area in cui il browser visualizza la pagina web), questo sarà interamente ricoperto dal colore di sfondo. Ciò accade indifferentemente, sia che la proprietà background-color venga impostata per l'elemento <html>, sia che venga impostata per l'elemento <body>:

html {
 border: solid 3px black;
 background-color: rgb(220,220,220);
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
}

Oppure:

html {
 border: solid 3px black;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgb(220,220,220);
}

Se, a partire da questa situazione, si tenta di modificare la posizione degli elementi <html> e <body> utilizzando le proprietà left, right, top oppure bottom, con unità di misura px oppure %, non si otterrà alcun risultato. Questo perché i due elementi sono di tipo static. All'impostazione delle proprietà contenenti le coordinate per il riposizionamento va accompagnata l'assegnazione di un valore relative oppure absolute alla proprietà position:

html {
 border: solid 3px black;
 background-color: rgb(220,220,220);
 position: absolute;
 top: 20%; /* oppure top: 150px; */
 left: 20%; /* oppure left: 250px; */
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
}

Come si può notare dalla figura, se si utilizza position: absolute, hanno effetto entrambe le proprietà top e left; ciò è ovvio nel caso si utilizzino i pixel come unità di misura. Nel caso dell'utilizzo di valori percentuali, invece, le proprietà sono efficaci perché, grazie alla proprietà position: absolute, si riferiscono alla dimensione effettiva del contenitore, ossia del viewport.

Inoltre, il blocco corrispondente all'elemento <html>, viene ridimensionato per essere contenuto orizzontalmente nella pagina (ciò, comunque, non accade se si forza la larghezza attraverso la proprietà width).

Se, invece, alla proprietà position si assegna il valore relative,

html {
 border: solid 3px black;
 background-color: rgb(220,220,220);
 position: relative;
 top: 20%;
 left: 15%; /* oppure left: 250px; */
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
}

allora la proprietà top non sarà efficace se le si assegna un valore percentuale; funzionerà invece con un valore in pixel.

Inoltre, si noti che il blocco corrispondente all'elemento <html> fuoriesce dal margine destro (facendo comparire una barra di scorrimento in basso). Questo perché, con il valore relative, l'elemento non viene estromesso dal normale flusso della pagina e la sua larghezza viene calcolata esattamente come era calcolata nel caso di position: static (cioè il valore di default). Solo successivamente il blocco viene spostato rispetto alla sua posizione static secondo quanto indicato dal valore left e/o dal valore top (quest'ultimo solo se espresso in pixel).

Proviamo ora ad applicare le stesse impostazioni all'elemento <body>:

html {
 border: solid 3px black;
 background-color: rgb(220,220,220);
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 position: absolute;
 top: 50%;
 left: 50%;
}

Estraendo l'elemento a cui è applicata dal flusso di renderizzazione degli elementi nella pagina, ed essendo applicata in questo caso all'elemento <body>, la proprietà position: absolute "svuota" l'elemento contenitore, ossia <html>, che infatti nella figura appare "collassato" (schiacciato) nella parte alta del viewport.

Per il resto, come ci aspettavamo, l'elemento <body> è stato posizionato secondo i valori percentuali di left e top, corrispondenti in questo caso al punto centrale del viewport. In questo caso, com'è ovvio, la proprietà margin non ha alcun effetto.

Anche in questo caso, dopo aver testato il valore absolute, passiamo a sperimentare il valore relative:

html {
 border: solid 3px black;
 background-color: rgb(220,220,220);
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 position: relative;
 top: 50%;
 left: 50%;
}

La prima considerazione da fare è che la proprietà margin torna ad essere efficace, e ciò è dimostrato dal fatto che, sebbene si sia posto left: 50%, il blocco corrispondente all'elemento <body> si trova più spostato verso destra (proprio della quantità margin) rispetto alla verticale che passa per il centro del viewport.

Anche in questo caso, la proprietà top espressa in percentuale non è efficace, in quanto non esiste un elemento contenitore con altezza definita rispetto al quale calcolare appunto il valore percentuale.

A questo punto passiamo a studiare il comportamento dei nostri due elementi rispetto all'inserimento di un'immagine di sfondo.

html {
 border: solid 3px black;
 background-image: url('Texture.jpg');
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
}

Come si può notare dalla figura, l'immagine, sebbene assegnata all'elemento <html>, ricopre tutto lo sfondo della finestra, anche al di fuori dei confini dell'elemento stesso (nell'esempio accade verticalmente, ma accadrebbe lo stesso anche lungo l'asse orizzontale, se all'elemento fosse assegnata una larghezza inferiore a quella della finestra).

Identico risultato si ottiene impostando la proprietà background-image dell'elemento <body>:

html {
 border: solid 3px black;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-image: url('Texture.jpg');
}

Questo caso specifico, in cui l'inserimento di un'immagine di sfondo causa una perdita di leggibilità del testo, ci permette di introdurre un'ulteriore possibilità: l'inserimento di un'immagine di sfondo nell'elemento <html> e di un colore di sfondo nell'elemento <body>:

html {
 border: solid 3px black;
 background-image: url('Texture.jpg');
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

E' interessante notare come in questo caso lo sfondo dell'elemento <body> sia confinato entro le dimensioni effettive dell'elemento, per lasciare spazio all'immagine di sfondo.

Con queste impostazioni, quando il testo ha una lunghezza tale da estendersi oltre l'altezza della finestra, l'immagine viene replicata verticalmente, come si può osservare nella figura a fianco, in cui all'incirca a metà dell'altezza della finestra si nota il confine tra due repliche successive. Per mostrare questo effetto abbiamo utilizzato un'immagine di sfondo che avesse un bordo ben visibile.

La stessa logica viene seguita per riempire orizzontalmente lo spazio della finestra: l'immagine, avendo una larghezza inferiore alla larghezza della finestra, viene replicata anche lungo la direzione orizzontale (notare il confine tra due repliche successive vicino al bordo destro della finestra).

Allo stesso modo, se la finestra viene ridotta di dimensioni, l'immagine viene "tagliata": viene così visualizzata solo la parte necessaria a coprire lo sfondo del viewport.

Se non si desidera che l'immagine venga replicata per coprire tutto lo sfondo del viewport, si può utilizzare la proprietà background-repeat, assegnandole il valore no-repeat. Per riempire lo spazio che in tal modo resterebbe "scoperto", si può utilizzare la proprietà background-color dell'elemento <body>.

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

Si noti l'utilizzo simultaneo della proprietà background-color per entrambi gli elementi <html> e <body>. Nel secondo, viene utilizzata per assegnare un colore di sfondo ai contenuti della pagina; nel primo, serve a colorare la parte del viewport che non viene coperta dall'immagine di sfondo a causa delle ridotte dimensioni di quest'ultima.

(Come ulteriore possibilità, si potrebbe desiderare che l'immagine sia ripetuta lungo un asse e non lungo l'altro. Per ottenere questo effetto si possono assegnare alla proprietà background-repeat i valori repeat-x oppure repeat-y.)

In questo caso specifico, lasciare una "striscia" scoperta lungo il margine destro del viewport non ha alcun senso. Dal momento che la larghezza dell'immagine arriva quasi a coprire la larghezza della finestra, si potrebbe pensare ad "allargarla" lungo l'asse orizzontale, senza correre il pericolo di peggiorarne eccessivamente la risoluzione.

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-size: 100% auto;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

L'immagine non viene deformata, perché viene "stirata" lungo l'asse verticale di una quantità proporzionale all'allungamento lungo l'asse orizzontale.

Per quanto riguarda l'asse verticale, si hanno ancora a disposizione entrambe le opzioni: replicare l'immagine (vedi codice precedente) oppure coprire lo spazio restante con un colore di sfondo (vedi codice seguente).

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-repeat: no-repeat;
 background-color: green;
 background-size: 100% auto;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

I due valori assegnati a background-size si riferiscono alle dimensioni orizzontale e verticale desiderate per l'immagine. Attenzione: i valori percentuali fanno riferimento alle dimensioni dell'elemento <html>, non a quelle del viewport.

Con il valore auto, invece, si intende non forzare la dimensione, lasciando che venga assegnata in maniera proporzionale (evitando di distorcere l'immagine).

Assegnando quindi 100% ad entrambe le dimensioni dello sfondo, si può ricoprire l'intero elemento <html> senza replicare l'immagine di sfondo. A questo punto risultano superflue le proprietà background-repeat e background-color.

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-size: 100% 100%;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

Nel nostro caso l'immagine è fortemente (e fastidiosamente) distorta. Questa impostazione può essere utile quando non causa una distorsione eccessiva; quando la distorsione non è un problema, come ad esempio nel caso l'immagine rappresenti una texture o un pattern geometrico in cui le proporzioni non siano importanti; quando, infine, l'allungamento non produce una riduzione di risoluzione intollerabile.

L'utilizzo del valore percentuale come dimensione dello sfondo produce inoltre un ridimensionamento (invece che un ritaglio) dell'immagine di sfondo quando si riducono le dimensioni della finestra. L'immagine di sfondo, pertanto, comparirà sempre per intero (ripetuta o meno a seconda del valore assegnato a background-repeat).

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-size: 100% auto;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

Questo stesso risultato può essere ottenuto utilizzando il valore contain:

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-size: contain;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

Vale la pena, infine, fare riferimento all'ultimo valore che può essere assegnato alla proprietà background-size: il valore cover.

html {
 border: solid 3px black;
 background-image: url('lilies.jpg');
 background-size: cover;
}
body {
 border: solid 3px red;
 width: 60%;
 margin: auto;
 background-color: rgba(230,230,230,0.5);
}

Mentre con contain vengono adattate le dimensioni dell'immagine in modo tale che essa sia completamente contenuta nell'elemento <html> (e poi replicata o meno a seconda del valore assegnato a background-repeat), lo scopo di cover è coprire l'elemento <html> (o, se questo è più piccolo, il viewport), evitando così ripetizioni dell'immagine ma provocandone, eventualmente, il ritaglio lungo uno degli assi.

Nel caso precedente l'adattamento della dimensione verticale dell'immagine ad un'altezza dell'elemento <html> di molte volte superiore ha prodotto una perdita di risoluzione ed un taglio lungo l'asse orizzontale che risultano intollerabili.

L'utilizzo di cover si presta molto meglio al caso rappresentato nell'immagine a fianco, in cui la differenza tra l'altezza dell'immagine e quella dell'elemento <html> non è eccessiva (il contenuto della pagina è molto più breve rispetto al caso precedente).